#include <iostream>
#include <string>

#include "boost/pfr.hpp"
#include "xlcomm/base/encode/json_helper.h"
using namespace xlcomm;

#define JSON_START
#define JSON_END

struct Work {
  std::string position;
  int money;
};

struct Person {
  std::string name;
  bool male;
  int age;
  Work work;

  bool FromJsonstr(const std::string& jsonstr) {
    Json::Value root;
    if (!JsonHelper::JsonstrToJson(jsonstr, root)) return false;

    bool ret = true;
    if (!JsonHelper::JsonToType(root["name"], name)) ret = false;
    if (!JsonHelper::JsonToType(root["male"], male)) ret = false;
    if (!JsonHelper::JsonToType(root["age"], age)) ret = false;
    if (!JsonHelper::JsonToType(root["work"]["position"], work.position))
      ret = false;
    if (!JsonHelper::JsonToType(root["work"]["money"], work.money)) ret = false;
    return ret;
  }

  void ToJsonstr(std::string& jsonstr) {
    Json::Value root;
    root["name"] = name;
    root["male"] = male;
    root["age"] = age;
    root["work"]["position"] = work.position;
    root["work"]["money"] = work.money;
    jsonstr = root.toStyledString();
  }
};

void TestJson() {
  Person person;
  std::string jsonstr = R"({"name":"ming", "male":false, "age":20,
    "work":{"position":"programer", "money":23}})";
  if (person.FromJsonstr(jsonstr)) {
    std::cout << "name:" << person.name << " male:" << person.male
              << " age:" << person.age
              << " work.position:" << person.work.position
              << " work.money:" << person.work.money << std::endl;
  }

  Person p2;
  p2.name = "LiMing";
  p2.work.money = 33;
  std::string tojson;
  p2.ToJsonstr(tojson);
  std::cout << tojson << std::endl;

  std::cout << boost::pfr::get<0>(p2) << std::endl;
}

int main() {
  Logger::SetLogLevel(Logger::kDebug);
  TestJson();
  return 0;
}